﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using DeviceMonitor.Classes.Model;
using System.Windows;
using WpfApplication1.Classes;
using DeviceMonitor.Utils;

namespace DeviceMonitor.Classes
{
    public delegate void MMSendMsg(Object msg);
    
    public class CanBusNet
    {
        public TcpClient mTcp;
        private const int READ_BUFFER_SIZE = 1000;
        private byte[] readBuffer = new byte[READ_BUFFER_SIZE + 1];
        private String _ip;
        private int _port;
        private List<String[]> cmdList = new List<string[]>();

        public event MMSendMsg sendMsgEvent;
        public int index;

        public CanBusNet(String ip, int port, int index = 0)
        {
            mTcp = new TcpClient();
            _ip = ip;
            _port = port;
            
            this.index = index;
        }
        public bool IsConnected()
        {
            return mTcp.Client.Connected;
        }
        public bool StartService()
        {
            if (mTcp.Client.Connected)
            {
                MessageBox.Show("已连接");
                return false;
            }
            //Can模块ip
            string mIPAddress = _ip;
            IPAddress hostIPAddress = IPAddress.Parse(mIPAddress);
            //端口
            int mPort = _port;
            IPEndPoint endIP = new IPEndPoint(hostIPAddress, mPort);

            try
            {
                //mTcp = new TcpClient(mIPAddress, mPort);
                var result = mTcp.BeginConnect(mIPAddress, mPort, null, null);

                var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));

                LogObject.WriteLog("canbus server 连接,ip:" + mIPAddress + ",port:" + mPort.ToString());

                if (!success)
                {
                    LogObject.WriteLog("canbus server connect error!","Error");
                    throw new Exception("Failed to connect.");
                }

                /*
                DateTime Savetime = DateTime.Now;
                TimeSpan n = new TimeSpan();
                while (true)
                {
                    //if (App.stopCanbusThread) break;
                    n = DateTime.Now - Savetime;
                    if (n.TotalMilliseconds > 5 || mTcp.Client.Connected) break;
                }
                if (!mTcp.Client.Connected) {
                    MessageBox.Show("连接失败");
                    return false;
                }
                */
                
                mTcp.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, DoRead, null);
            }
            catch (Exception ex)
            {
                //MessageBox.Show("CAN模块"+ (index+1) .ToString()+ "连接失败");
                return false;
            }
            return true;
        }
        private void DoRead(IAsyncResult ar)
        {
            try
            {
                int BytesRead = mTcp.GetStream().EndRead(ar);
                if (BytesRead > 0)
                {
                    /*string hexStr = "";
                    for (int i = 0; i <= BytesRead - 1; i++)
                    {
                        hexStr = hexStr + string.Format("{0:x2}", readBuffer[i]) + " ";
                    }*/

                    //处理报文
                    //string[] cmdArray = hexStr.Split(' ');

                    int counter = BytesRead / 13;
                    for (int i = 0; i < counter; i++)
                    {
                        string hexStr = "";
                        for (int j = 0; j < 13; j++)
                        {
                            int idx = (i * 13) + j;
                            hexStr = hexStr + string.Format("{0:x2}", readBuffer[idx]) + " ";
                        }
                        LogObject.WriteLog("receive message: " + hexStr, "Debug");
                        //if (sendMsgEvent != null)
                        //{
                        //sendMsgEvent(hexStr);
                        //}
                        //Console.WriteLine(hexStr);
                        //LogObject.WriteLog(hexStr);
                        //sendMsg("接收报文: " + hexStr);

                        string[] cmdArray = hexStr.Split(' ');
                        //List<String[]> cmdList = new List<string[]>();
                        if (cmdArray[3].Equals("62"))
                        {
                            bool flag = true;
                            if (cmdList.Count() == 0)
                            {
                                if (!"40".Equals(cmdArray[5]))
                                {
                                    //忽略
                                    flag = false;
                                }
                            }
                            if (flag)
                            {
                                cmdList.Add(cmdArray);
                            }
                            if (cmdList.Count() == 5)
                            {
                                List<String[]> cmdListCopy = new List<String[]>();
                                foreach (String[] itme in cmdList)
                                {
                                    String[] cmdCopy = new String[14];
                                    itme.CopyTo(cmdCopy, 0);
                                    cmdListCopy.Add(cmdCopy);
                                }
                                DealCmds("62", cmdListCopy);
                                cmdList.Clear();
                            }
                        }
                        else if (cmdArray[3].Equals("43"))
                        {
                            bool flag = true;
                            if (cmdList.Count() == 0)
                            {
                                if (!"40".Equals(cmdArray[5]))
                                {
                                    //忽略
                                    flag = false;
                                }
                            }
                            if (flag)
                            {
                                cmdList.Add(cmdArray);
                            }
                            if (cmdList.Count() == 8)
                            {
                                List<String[]> cmdListCopy = new List<String[]>();
                                foreach (String[] itme in cmdList)
                                {
                                    String[] cmdCopy = new String[14];
                                    itme.CopyTo(cmdCopy, 0);
                                    cmdListCopy.Add(cmdCopy);
                                }
                                DealCmds("63", cmdListCopy);
                                cmdList.Clear();
                            }
                        }
                        else if (cmdArray[3].Equals("48"))
                        {
                            String address = cmdArray[4];
                            if ("04".Equals(address))
                            {
                                //下传提单信息应答
                                List<String[]> cmdListCopy = new List<String[]>();
                                String[] cmdCopy = new String[14];
                                cmdArray.CopyTo(cmdCopy, 0);
                                cmdListCopy.Add(cmdCopy);
                                DealCmds("6804", cmdListCopy);
                            }
                            else if ("05".Equals(address))
                            {
                                //下传提单信息应答
                                List<String[]> cmdListCopy = new List<String[]>();
                                String[] cmdCopy = new String[14];
                                cmdArray.CopyTo(cmdCopy, 0);
                                cmdListCopy.Add(cmdCopy);
                                DealCmds("6805", cmdListCopy);
                            }
                        }
                    }

                    mTcp.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, DoRead, null);
                }
            }
            catch (Exception e)
            {
                //LogObject.WriteLog(e.ToString());
                if (sendMsgEvent != null)
                {
                    sendMsgEvent(e.ToString());
                }
                mTcp.Client.Close();
            }
        }

        public void SendData(string temperature, bool check)
        {
            if (!mTcp.Client.Connected)
            {
                return;
            }
            string sendMessage = App.GetConfig().sendMessage;
            if (!"true".Equals(sendMessage)) return;

            string[] tmp = temperature.Split(' ');
            var buf = new byte[22];

            for (int i = 0; i < buf.Length; i++)
            {
                buf[i] = 0;
            }
            for (int i = 0; i < tmp.Length; i++)
            {
                try
                {
                    buf[i] = Convert.ToByte(tmp[i], 16);
                }
                catch (Exception e)
                {
                    buf[i] = 0;
                }
            }
            SendData(buf, 0, 13, check);
        }

        public bool SendData(byte[] sendBytes, int mStart, int mLen, bool check = true)
        {
            if (!check) return false;
            try
            {
                lock (mTcp.GetStream())
                {
                    mTcp.GetStream().Write(sendBytes, mStart, mLen);
                }
                return true;
            }
            catch (Exception x)
            {
                //LogObject.WriteLog("发送报文失败: " + x.ToString());
                //sendMsg("发送报文失败: " + x.ToString());
                LogObject.WriteLog("发送报文失败: " + x.ToString(), "Error");
                return false;
            }
        }

        public bool StopService()
        {
            bool _result = false;
            if (!mTcp.Client.Connected)
            {
                return false;
            }
            try
            {
                mTcp.Client.Disconnect(_result);
                mTcp.Client.Close();
            }
            catch (Exception ex)
            {
                _result = false;
            }
            return _result;
        }

        public void DealCmds(String type, List<String[]> cmdArray)
        {
            //LogObject.WriteLog("DealCmds type:" + type);
            try
            {
                if ("62".Equals(type))
                {
                    Message62 msgObj = new Message62();
                    msgObj.ServiceIndex = index;

                    String idStr = cmdArray.ElementAt(0)[1].Substring(1, 1) + cmdArray.ElementAt(0)[2].Substring(0, 1);
                    int id = Convert.ToInt32("0x" + idStr, 16) / 2;
                    msgObj.Id = id;

                    String orderCode8 = cmdArray.ElementAt(3)[7] + cmdArray.ElementAt(3)[8] + cmdArray.ElementAt(3)[9] + cmdArray.ElementAt(3)[10];
                    msgObj.OrderCode = orderCode8;

                    String flow = cmdArray.ElementAt(0)[6] + cmdArray.ElementAt(0)[7] + "." + cmdArray.ElementAt(0)[8] + cmdArray.ElementAt(0)[9];
                    Double dblFlow = Double.Parse(flow) * 3.6;
                    msgObj.Flow = dblFlow;

                    String tempChar = cmdArray.ElementAt(0)[10].Substring(0, 1);
                    String tempStr = cmdArray.ElementAt(0)[10].Substring(1, 1) + cmdArray.ElementAt(0)[11].Substring(0, 1) + "." + cmdArray.ElementAt(0)[11].Substring(1, 1);
                    Double dblTemp = 0.0;
                    if ("0".Equals(tempChar))
                    {
                        dblTemp = Double.Parse(tempStr);
                    }
                    else
                    {
                        dblTemp = Double.Parse("-" + tempStr);
                    }
                    msgObj.Temp = dblTemp;

                    String densityStr = cmdArray.ElementAt(0)[12] + cmdArray.ElementAt(1)[6] + "." + cmdArray.ElementAt(1)[7] + cmdArray.ElementAt(1)[8];
                    Double dblDensity = Double.Parse(densityStr);
                    msgObj.Density = dblDensity;

                    //Double dblShouldVolume  = Double.Parse(cmdArray.ElementAt(2)[10] + cmdArray.ElementAt(2)[11] + cmdArray.ElementAt(2)[12] + cmdArray.ElementAt(3)[6].Substring(0, 1) + "." + cmdArray.ElementAt(3)[6].Substring(1, 1));
                    Double dblShouldVolume = Double.Parse(cmdArray.ElementAt(1)[9] + cmdArray.ElementAt(1)[10] + cmdArray.ElementAt(1)[11] + cmdArray.ElementAt(1)[12]);
                    msgObj.ShouldVolume = dblShouldVolume;

                    Double actVolume = Double.Parse(cmdArray.ElementAt(2)[6] + cmdArray.ElementAt(2)[7] + cmdArray.ElementAt(2)[8] + cmdArray.ElementAt(2)[9].Substring(0, 1) + "." + cmdArray.ElementAt(2)[9].Substring(1, 1));
                    Double actWeight = Double.Parse(cmdArray.ElementAt(2)[10] + cmdArray.ElementAt(2)[11] + cmdArray.ElementAt(2)[12] + cmdArray.ElementAt(3)[6].Substring(0, 1) + "." + cmdArray.ElementAt(3)[6].Substring(1, 1));
                    msgObj.ActWeight = actWeight;
                    msgObj.ActVolume = actVolume;

                    String status = cmdArray.ElementAt(3)[11];
                    String status2 = cmdArray.ElementAt(3)[12];
                    if ("55".Equals(status))
                    {
                        status = "1";
                    }
                    else if ("00".Equals(status))
                    {
                        status = "0";
                    }
                    else if ("0A".Equals(status))
                    {
                        status = "2";
                    }
                    else
                    {
                        status = "2";
                    }
                    msgObj.Status = status;

                    String unit = cmdArray.ElementAt(4)[6];
                    if ("55".Equals(unit))
                    {
                        unit = "公斤";
                    }
                    else
                    {
                        unit = "公升";
                    }
                    msgObj.Unit = unit;

                    String mode = cmdArray.ElementAt(4)[7];
                    if ("55".Equals(mode))
                    {
                        mode = "本地";
                    }
                    else
                    {
                        mode = "联网";
                    }
                    msgObj.Mode = mode;

                    String checkStatus = cmdArray.ElementAt(4)[8];
                    if ("55".Equals(checkStatus))
                    {
                        checkStatus = "等待验卡";
                    }
                    else
                    {
                        checkStatus = "验卡完成";
                    }
                    msgObj.CheckStatus = checkStatus;

                    String alerm = cmdArray.ElementAt(4)[9];
                    int val = Convert.ToInt32(alerm, 16);
                    string alermStr = Convert.ToString(val, 2).PadLeft(8, '0');
                    msgObj.Alerm = alermStr;

                    MessageDeal.DealMessage62(index, msgObj);

                    sendMsg(msgObj);
                }
                else if ("63".Equals(type))
                {
                    Message63 msgObj = new Message63();
                    msgObj.ServiceIndex = index;

                    String idStr = cmdArray.ElementAt(0)[1].Substring(1, 1) + cmdArray.ElementAt(0)[2].Substring(0, 1);
                    int id = Convert.ToInt32("0x" + idStr, 16) / 2;
                    msgObj.Id = id;

                    //员工号
                    String operatorCode = cmdArray.ElementAt(0)[6] + cmdArray.ElementAt(0)[7];
                    msgObj.OperatorCode = operatorCode;

                    String materialCode = cmdArray.ElementAt(0)[8] + cmdArray.ElementAt(0)[9] + cmdArray.ElementAt(0)[10] + cmdArray.ElementAt(0)[11] + cmdArray.ElementAt(0)[12];
                    msgObj.MaterialCode = materialCode;

                    String startTime = "20" + cmdArray.ElementAt(1)[10] + "-" + cmdArray.ElementAt(1)[11] + "-" + cmdArray.ElementAt(1)[12] + " " + cmdArray.ElementAt(2)[10] + ":" + cmdArray.ElementAt(1)[11] + ":" + cmdArray.ElementAt(1)[12];
                    msgObj.StartTime = startTime;

                    String shouldNum = cmdArray.ElementAt(2)[6] + cmdArray.ElementAt(2)[7] + cmdArray.ElementAt(2)[8] + cmdArray.ElementAt(2)[9];
                    msgObj.ShouldNum = shouldNum;

                    String actNum = cmdArray.ElementAt(3)[6] + cmdArray.ElementAt(3)[7] + cmdArray.ElementAt(3)[8] + cmdArray.ElementAt(3)[9].Substring(0, 1) + "." + cmdArray.ElementAt(3)[9].Substring(1, 1);
                    msgObj.ActNum = actNum;
                    String actVolumeNum = cmdArray.ElementAt(4)[6] + cmdArray.ElementAt(4)[7] + cmdArray.ElementAt(4)[8] + cmdArray.ElementAt(4)[9].Substring(0, 1) + "." + cmdArray.ElementAt(4)[9].Substring(1, 1);
                    msgObj.ActVolumeNum = actVolumeNum;

                    String endTime = "20" + cmdArray.ElementAt(3)[10] + "-" + cmdArray.ElementAt(3)[11] + "-" + cmdArray.ElementAt(3)[12] + " " + cmdArray.ElementAt(4)[10] + ":" + cmdArray.ElementAt(4)[11] + ":" + cmdArray.ElementAt(4)[12];
                    msgObj.EndTime = endTime;

                    String beginWeightMeterNumStr = cmdArray.ElementAt(5)[9] + cmdArray.ElementAt(5)[8] + cmdArray.ElementAt(5)[7] + cmdArray.ElementAt(5)[6];
                    String beginMeterNum = MessageUtils.getFloatFromHex(beginWeightMeterNumStr).ToString();
                    msgObj.BeginMeterNum = beginMeterNum;

                    String endWeightMeterNumStr = cmdArray.ElementAt(6)[9] + cmdArray.ElementAt(6)[8] + cmdArray.ElementAt(6)[7] + cmdArray.ElementAt(6)[6];
                    String endMeterNum = MessageUtils.getFloatFromHex(endWeightMeterNumStr).ToString();
                    msgObj.EndMeterNum = endMeterNum;
                    
                    String orderCode = cmdArray.ElementAt(7)[6] + cmdArray.ElementAt(7)[7] + cmdArray.ElementAt(7)[8] + cmdArray.ElementAt(7)[9];
                    msgObj.OrderCode = orderCode;

                    try
                    {
                        /*
                        String tempChar = cmdArray.ElementAt(7)[10].Substring(0, 1);
                        String tempStr = cmdArray.ElementAt(7)[10].Substring(1, 1) + cmdArray.ElementAt(7)[11].Substring(0, 1) + "." + cmdArray.ElementAt(7)[11].Substring(1, 1);
                        Double dblTemp = 0.0;
                        if ("0".Equals(tempChar))
                        {
                            dblTemp = Double.Parse(tempStr);
                        }
                        else
                        {
                            dblTemp = Double.Parse("-" + tempStr);
                        }
                        msgObj.Temp = dblTemp.ToString();
                        */
                    }
                    catch
                    {
                        msgObj.Temp = "0.00";
                    }
                    msgObj.Temp = "0.00";

                    String densityStr = cmdArray.ElementAt(5)[10] + cmdArray.ElementAt(5)[11] + "." + cmdArray.ElementAt(6)[10] + cmdArray.ElementAt(6)[11];
                    Double dblDensity = Double.Parse(densityStr);
                    msgObj.Density = dblDensity.ToString();

                    MessageDeal.DealMessage63(index, msgObj);
                    sendMsg(msgObj);
                }
                else if ("6804".Equals(type))
                {
                    Message68 msgObj = new Message68();
                    msgObj.ServiceIndex = index;

                    String idStr = cmdArray.ElementAt(0)[1].Substring(1, 1) + cmdArray.ElementAt(0)[2].Substring(0, 1);
                    int id = Convert.ToInt32("0x" + idStr, 16) / 2;
                    msgObj.Id = id;

                    MessageDeal.DealMessage6804(index, msgObj);
                }
                else if ("6805".Equals(type))
                {
                    Message68 msgObj = new Message68();
                    msgObj.ServiceIndex = index;

                    String idStr = cmdArray.ElementAt(0)[1].Substring(1, 1) + cmdArray.ElementAt(0)[2].Substring(0, 1);
                    int id = Convert.ToInt32("0x" + idStr, 16) / 2;
                    msgObj.Id = id;

                    MessageDeal.DealMessage6805(index, msgObj);
                }
            }catch(Exception ex)
            {
                //LogObject.WriteLog("解析报文失败: " + ex.ToString());
            }
        }
        private void sendMsg(Object msg)
        {
            if (sendMsgEvent != null)
            {
                Console.WriteLine("---------sendMsgEvent-----");
                sendMsgEvent(msg);
            }
        }
    }
}
